<?php


namespace services\buss;


use common\helpers\RedisHelper;
use common\models\base\CommonStatus;
use common\models\base\Department;
use common\models\base\Project;
use common\models\buss\CommonRelation;
use common\models\buss\Scard;
use common\models\member\Member;
use services\base\CommonRelationService;
use services\base\DepartmentService;
use services\log\LogMemberOpService;
use services\member\MemberService;
use Yii;
use common\components\Service;
use common\helpers\CommonHelper;
use common\models\buss\Devices;

class DevicesService extends Service
{
    /**
     * 设备列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function devicesList(array $params, int $page, int $pageSize): array
    {
        $query = Devices::find()
            ->alias('d')
            ->select(['d.*', 'GROUP_CONCAT(s.sim_card) sim_card', 'GROUP_CONCAT(cr.relation_id) sim_card_id'])
            ->leftJoin(CommonRelation::tableName() . ' cr', 'd.id = cr.primary_id and cr.type = ' . CommonRelation::TYPE_DEVICES)
            ->leftJoin(Scard::tableName() . ' s', 'cr.relation_id = s.id')

            ->where([
                'd.status' => [
                    Devices::STATUS_ENABLE,
                    Devices::STATUS_INVALID
                ],
//                'd.project_id' => array_column(MemberService::getAllProjectListCondition(), 'value')
            ])->groupBy('d.id');

        // 权限【项目、部门】
        $memberAuth = MemberService::getLoginMemberLimit();
        // 是超管直接跳过
        if ($memberAuth['super_type'] != Member::SUPER_TYPE_SUPER_ADMIN) {
            // 是否为项目管理员
            if ($memberAuth['admin_project_ids']) {
                $query->andWhere([
                    'or',
                    ['d.project_id' => $memberAuth['admin_project_ids']],// 是【一个或几个】项目管理员则查全项目数据
                    [
                        'd.department_id' => $memberAuth['all_department_ids'],
                        'd.project_id' => $memberAuth['member_project_ids'],
                        'd.use_mid' => $memberAuth['all_member_ids'],
                    ]
                ]);
            } else {
                $query->andWhere([
                    'd.department_id' => $memberAuth['all_department_ids'],
                    'd.project_id' => $memberAuth['member_project_ids'],
                    'd.use_mid' => $memberAuth['all_member_ids'],
                ]);
            }
        }

        // 搜索关键词
        if (isset($params['keywords']) && $params['keywords']) {
            if (is_numeric(trim($params['keywords']))) {
                $query->andWhere(['like', 's.sim_card', "{$params['keywords']}%", false]);
            } else {
                $query->andWhere(['like', 'd.name', $params['keywords']]);
            }
        }
        // 项目
        if (isset($params['project_id']) && $params['project_id']) {
            $query->andWhere(['d.project_id' => $params['project_id']]);
        }
        // 部门
        if (isset($params['department_id']) && $params['department_id']) {
            $allIds = $params['department_id'];
            $department = RedisHelper::getDepartment($params['department_id']);
            if ($department->data_level == Department::DATA_LEVEL_DEPARTMENT_ALL) {
                $childDepartmentList = DepartmentService::getChildDepartmentList($department->tree_id);
                $allIds = array_merge([$department->id], array_column($childDepartmentList, 'id'));
            }
            $query->andWhere(['d.department_id' => $allIds]);
        }
        // 使用人
        if (isset($params['use_mid']) && $params['use_mid']) {
            $query->andWhere(['d.use_mid' => $params['use_mid']]);
        }
        // 状态
        if (isset($params['status']) && is_numeric($params['status'])) {
            $query->andWhere(['d.status' => $params['status']]);
        }

        $list = $this->getListPageRes($query, $page, $pageSize, ['d.status' => SORT_DESC, 'd.id' => SORT_DESC]);
        foreach ($list['list'] as &$val) {
            $project = $val['project_id'] ? RedisHelper::getProject($val['project_id']) : '';
            $val['project_name'] = $project && $project->status != Project::STATUS_DELETE ? $project->project_name : '';
//            $department = $val['department_id'] ? RedisHelper::getDepartment($val['department_id']) : '';
//            $val['department_name'] = $department && $department->status != Department::STATUS_DELETE ? $department->department_name : '';
            $departmentName = DepartmentService::getParent($val['department_id']);
            $val['department_name'] = implode(' / ', $departmentName);
            $member = $val['use_mid'] ? RedisHelper::getMember($val['use_mid']) : '';
            $val['use_mname'] = $member && $member->status != Member::STATUS_DELETE ? $member->realname : '';
            $val['status_name'] = Devices::$statuss[$val['status']] ?? '';
            $val['sim_card'] = explode(',', $val['sim_card']);
            $val['sim_card_id'] = explode(',', $val['sim_card_id']);
        }
        return $list;
    }

    /**
     * 状态下拉筛选项
     * @return array[]
     */
    public static function getStatusCondition(): array
    {
        return [
            ['value' => Devices::STATUS_ENABLE, 'label' => Devices::$statuss[Devices::STATUS_ENABLE]],
            ['value' => Devices::STATUS_INVALID, 'label' => Devices::$statuss[Devices::STATUS_INVALID]],
        ];
    }

    /**
     * 使用人下拉筛选项
     * @return array[]
     */
    public static function getUseMemberCondition(): array
    {
        $query = Devices::find()
            ->alias('d')
            ->select(['d.use_mid value', 'm.realname label'])
            ->leftJoin(Member::tableName() . ' m', 'm.id = d.use_mid')
            ->where(['d.status' => [Devices::STATUS_ENABLE, Devices::STATUS_INVALID]]);

        $memberAuth = MemberService::getLoginMemberLimit();
        // 是超管直接跳过
        if ($memberAuth['super_type'] != Member::SUPER_TYPE_SUPER_ADMIN) {
            // 是否为项目管理员
            if ($memberAuth['admin_project_ids']) {
                $query->andWhere([
                    'or',
                    ['d.project_id' => $memberAuth['admin_project_ids']],// 是【一个或几个】项目管理员则查全项目数据
                    ['d.use_mid' => $memberAuth['all_member_ids']]
                ]);
            } else {
                $query->andWhere(['d.use_mid' => $memberAuth['all_member_ids']]);
            }
        }
        return $query->andWhere(['!=', 'd.use_mid' , 0])
            ->groupBy('d.use_mid')
            ->asArray()
            ->all();
    }


    /**
     * 获取设备列表【正常 + 禁用】
     * @param int|array|null $ids
     * @return CommonStatus[]
     */
    public static function getNormalListByIds($ids = null): array
    {
        $query = Devices::find()
            ->select(['*'])
            ->where([
                'status' => [Devices::STATUS_INVALID, Devices::STATUS_ENABLE],
            ]);
        if (is_array($ids)) {
            $query->andWhere(['id' => $ids]);
        }
        return $query->orderBy(['id' => SORT_ASC])->all();
    }

    /**
     * 获取正常的设备数据
     * @param int|array|null $orIds
     * @return array
     */
    public static function getEnableListByIds($orIds = null): array
    {
        $query = Devices::find()
            ->select(['*'])
            ->where(['status' => Devices::STATUS_ENABLE]);
        if (!is_null($orIds)) {
            $query->orWhere([
                'id' => $orIds,
                'status' => [Devices::STATUS_ENABLE, Devices::STATUS_INVALID]
            ]);
        }
        return $query->orderBy(['id' => SORT_ASC])->all();
    }

    /**
     * 获取设备列表下拉筛选
     * 获取下拉列表筛选项
     * @return array
     */
    public static function getListCondition(): array
    {
        return CommonHelper::getListCondition(self::getNormalListByIds(), ['value_column' => 'id', 'label_column' => 'name']);
    }

    /**
     * 获取编辑下拉筛选项
     * @param int|array|null $orIds
     * @return array
     */
    public static function getEditCondition($orIds = null): array
    {
        return CommonHelper::getListCondition(self::getEnableListByIds($orIds), ['value_column' => 'id', 'label_column' => 'name']);
    }

    /**
     * 更新设备
     * @throws \Exception
     */
    public function updateDevices(array $params)
    {
        $devices = new Devices();
        $scenario = 'create';
        $oldDevices = null;
        // 是否为编辑，编辑判断排除当前ID
        $whereId = [];
        if ($params['id']) {
            $whereId = ['!=', 'id', $params['id']];
            // 设备表
            $oldDevices = self::getData($params['id']);
            $devices = Devices::findOne($params['id']);
            $scenario = 'edit';
        }
        // 判断名称是否存在
        $check = Devices::find()
            ->select(['id'])
            ->where([
                'name' => $params['name'],
                'status' => [Devices::STATUS_ENABLE, Devices::STATUS_INVALID]
            ])
            ->andWhere($whereId)
            ->asArray()
            ->one();
        if ($check) {
            return CommonHelper::api(422, '名称已存在');
        }

        // 判断手机号是否被绑定
        $checkDevicesMobile = $this->checkDevicesMobile(['mobile' => explode(',', $params['mobile']), 'primary_id' => $params['id']]);
        if ($checkDevicesMobile) {
            return CommonHelper::api(422, '手机号已被绑定');
        }

        $transaction = Yii::$app->db->beginTransaction();
        try {
            $devices->project_id = $params['project_id'];
            $devices->department_id = $params['department_id'];
            $devices->phone_model = $params['phone_model'] ?: '';
            $devices->name = $params['name'];
            $devices->use_mid = isset($params['use_mid']) && $params['use_mid'] ? $params['use_mid'] : 0;
            $devices->remark = $params['remark'] ?: '';
            $devices->status = $params['status'] ?? Devices::STATUS_ENABLE;
            $devices->operation_id = Yii::$app->user->identity->member_id;
            $devices->operation_name = Yii::$app->user->identity->member->realname;
            $devices->saveAndCheckResult();

            $oldMobile = CommonRelationService::getCommonRelationListByPrimaryId($devices->id, CommonRelation::TYPE_DEVICES);
            // 设备解绑手机卡
            CommonRelationService::unbindByPrimaryId(CommonRelation::TYPE_DEVICES, $devices->id);

            // 设备手机卡绑定
            $mobileArr = [];
            if (isset($params['mobile']) && $params['mobile']) {
                $mobileArr = explode(',', $params['mobile']);
                $this->createDevicesMobile(['primary_id' => $devices->id, 'mobile' => $mobileArr]);
            }

            $oldMobileArr = [];
            if ($oldMobile) {
                $oldMobileArr = array_column($oldMobile, 'relation_id');
            }
            // 添加日志
            LogMemberOpService::createDeviceLog($scenario, $devices, $oldDevices, $mobileArr, $oldMobileArr);

            $transaction->commit();
            return ['id' => $devices->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 设备
     * @param int $id
     * @return Devices|null
     */
    public static function getData(int $id): ?Devices
    {
        return Devices::findOne($id);
    }

    /**
     * 判断手机号是否被绑定
     */
    public function checkDevicesMobile(array $params)
    {
        return  CommonRelation::find()
            ->where(['relation_id' => $params['mobile'], 'type' => CommonRelation::TYPE_DEVICES])
            ->andWhere(['!=', 'primary_id', $params['primary_id']])
            ->asArray()
            ->one();
    }

    /**
     * 设备手机卡绑定表
     */
    public function createDevicesMobile(array $params): void
    {
        $addArr = [];
        foreach ($params['mobile'] as $val) {
            $add['primary_id'] = $params['primary_id'];
            $add['relation_id'] = $val;
            $add['type'] = CommonRelation::TYPE_DEVICES;
            $add['operation_id'] = Yii::$app->user->identity->member_id;
            $add['operation_name'] = Yii::$app->user->identity->member->realname;
            $add['created_at'] = time();
            $add['updated_at'] = time();
            $addArr[] = $add;
        }
        if ($addArr) {
             Yii::$app->db->createCommand()->batchInsert(
                 CommonRelation::tableName(),
                ['primary_id', 'relation_id', 'type', 'operation_id', 'operation_name', 'created_at', 'updated_at'],
                $addArr
             )->execute();
        }
    }

    /**
     * 设备删除
     */
    public function deleteDevices(array $params): array
    {
        $transaction = Yii::$app->db->beginTransaction();
        try {
            // 更新设备状态为-1
            Devices::updateAll([
                'status' => Devices::STATUS_DELETE,
                'operation_id' => Yii::$app->user->identity->member_id,
                'operation_name' => Yii::$app->user->identity->member->realname,
                'updated_at' => time()
            ], ['id' => $params['id']]);

            // 设备解绑手机卡
            CommonRelationService::unbindByPrimaryId(CommonRelation::TYPE_DEVICES, $params['id']);

            // 添加日志
            LogMemberOpService::createDeviceLog('delete', self::getData($params['id']));
            $transaction->commit();
            return ['id' => $params['id']];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 人员删除部门解除绑定人员数据
     * @param int $memberId
     * @param $departmentIds
     * @return void
     */
    public static function clearUseMid(int $memberId, $departmentIds): void
    {
        Devices::updateAll(['use_mid' => 0], ['department_id' => $departmentIds, 'use_mid' => $memberId]);
    }

    /**
     * 根据项目统计设备数
     * @param $projectIds
     * @return array
     */
    public static function getStaticsNumByProject($projectIds): array
    {
        return Devices::find()
            ->select(['project_id', 'COUNT(*) devices_num'])
            ->where([
                'project_id' => $projectIds,
            ])
            ->andWhere(['!=', 'status', Devices::STATUS_DELETE])
            ->indexBy('project_id')
            ->groupBy('project_id')
            ->asArray()
            ->all();
    }
}
